/*
 * @Author: your name
 * @Date: 2020-08-01 07:26:52
 * @LastEditTime: 2020-08-01 12:16:36
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /Projects/linux/Program/客服系统/src/online_server_list.c
 */ 
#include "../include/online_server_list.h"
/*
	功能：输出错误，并且结束进程
	参数：s：出错信息字符串
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void perr_exit(const char *s){
	perror(s);
	exit(1);
}
/*
	功能：创建链表头节点
	参数：无
	返回值：链表头节点指针
	作者：ljj
	时间：2020/8/1
*/
ONLINESERVENODE *creat_onlineServeNode_list(){

	ONLINESERVENODE *head = (ONLINESERVENODE*)malloc(sizeof(ONLINESERVENODE));
	if (head == NULL){
		perr_exit("fail to creat onlineServeNode_list");
	}
	head->next = NULL;
	
	return head;	
}

/*
	功能：根据id，和name,socketfd创建节点
	参数：id：用户的id， name：用户的名字 socketfd:客户连接标识符
	返回值：节点指针
	作者：ljj
	时间：2020/8/1
*/
ONLINESERVENODE *creat_onlineServeNode_by_information(const char *id, const char *name, int socketfd){
	
    ONLINESERVENODE *node = (ONLINESERVENODE *)malloc(sizeof(ONLINESERVENODE));
	if (node == NULL){
		perr_exit("fail to creat onlineServeNode");
	}
	//为id和name申请动态内存,并赋值
	node->id = (char *)malloc(strlen(id) + 1); 
    node->name = (char *)malloc(strlen(name) + 1);
	strcpy(node->name, id);
    strcpy(node->name, name);
	node->socketfd = socketfd;
	node->customSocketFd = -1;
	node->waitCustomNum = 0;
	//链接
    node->next = NULL;

    return node;
}
/*
	功能：根据id，和name,socketfd创建节点,并且加入链表
	参数：id：用户的id， name：用户的名字 socketfd:和用户绑定的套接字
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void add_onlineServeNode(ONLINESERVENODE *head, const char *id, const char *name, int socketfd){
	
    if (head == NULL){
		perr_exit("head is NULL");
    }
    ONLINESERVENODE *index = head;
	//找到链表尾部
    while (index->next != NULL){
        index = index->next;
    }
	ONLINESERVENODE* node = creat_onlineServeNode_by_information(id, name, socketfd);
    index->next = node;
}
/*
	功能：根据用户id账号查找节点
	参数：head：链表头指针， id:用户id账号
	返回值：查找到的节点指针,查找不到返回NULL
	作者：ljj
	时间：2020/8/1
*/
ONLINESERVENODE *find_onlineServeNode_by_id(ONLINESERVENODE *head, const char *id){

    if (head == NULL){
        perr_exit("head is NULL");
    }

    ONLINESERVENODE *index = head->next;

    while (index != NULL){
        if (strcmp(index->id, id) != 0){
            index = index->next;
        } else {
            return index;
        }
    }
    return NULL;
}
/*
	功能：根据用户名查找节点
	参数：head：链表头指针， name:用户名
	返回值：查找到的节点指针，查找不到返回NULL
	作者：ljj
	时间：2020/8/1
*/
ONLINESERVENODE *find_onlineServeNode_by_name(ONLINESERVENODE *head, const char *name){

    if (head == NULL){
        perr_exit("head is NULL");
    }

    ONLINESERVENODE *index = head->next;

    while (index != NULL){
        if (strcmp(index->name, name) != 0){
            index = index->next;
        } else {
            return index;
        }
    }
    return NULL;
}
/*
	功能：更新客服的正在服务的客户的连接标识符
	参数：head：在线客服链表头指针， id：客服的id    customSocketFd:要更新的即将服务的客户的连接标识符
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void update_onlineServeNode_customSocketFd_by_id(ONLINESERVENODE* head, const char *id, int customSocketFd){

	ONLINESERVENODE *node = find_onlineServeNode_by_id(head, id);
	if (node == NULL) {
		perror("update faile:Server id is not exist");
	}
	node->customSocketFd = customSocketFd;
}
/*
	功能：更新客服的等待服务的客户人数
	参数：head：在线客服链表头指针， id：客服的id    waitCustomNum:要更新的等待服务的客户人数
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void update_onlineServeNode_waitCustomNum_by_id(ONLINESERVENODE* head, const char *id, int waitCustomNum){

	ONLINESERVENODE *node = find_onlineServeNode_by_id(head, id);
	if (node == NULL) {
		perror("update faile:Server id is not exist");
	}
	node->waitCustomNum = waitCustomNum;
}

/*
	功能：删除节点,释放malloc出来的内存
	参数：node：二级节点指针
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void del_onlineServeNode(ONLINESERVENODE **node){

	destory_onlineCustomNode_list(&((*node)->waitCustomList));
    (*node)->next = NULL;
	//释放id占用的动态内存
    if ((*node)->id != NULL){
        free((*node)->id);
        (*node)->id = NULL;
    }
	//释放name占用的动态内存
    if ((*node)->name != NULL){
        free((*node)->name);
        (*node)->name = NULL;
    }
	//释放node指针占用的内存
    free(*node);
    *node = NULL;
}
/*
	功能：根据id账号删除节点
	参数：head：链表头指针， id:用户id账号
	返回值：-1：删除失败   0:删除成功
	作者：ljj
	时间：2020/8/1
*/
int del_onlineServeNode_by_id(ONLINESERVENODE *head, const char *id){

    if (head == NULL){
        perr_exit("head is NULL");
    }
	//单链表双指针删除操作
    ONLINESERVENODE *index = head->next;
    ONLINESERVENODE *index2 = head;
    while (index != NULL){
        if (strcmp(index->id, id) == 0){
            break;
        } else {
            index2 = index;
            index = index->next;
        }
    }
	//找不到要删除的节点，直接返回删除失败-1
    if (index == NULL){
		perror("delete fail:can not find server id");
        return -1;
    }
    index2->next = index->next;
	//释放内存
    del_onlineServeNode(&index);
	return 0;
}
/*
	功能：清空链表，删除所有节点
	参数：head：链表头指针
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void clear_onlineServeNode_list(ONLINESERVENODE *head)
{
    if (head == NULL){
        perr_exit("head is NULL");
    }
    ONLINESERVENODE *index = head->next;
    while (index != NULL){
        head->next = index->next;
        del_onlineServeNode(&index);
        index = head->next;
    }
}
/*
	功能：摧毁链表
	参数：head：链表头指针
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void destory_onlineServeNode_list(ONLINESERVENODE **head)
{
    clear_onlineServeNode_list(*head);
    free(*head);
    *head = NULL;
}

/*
	功能：打印节点信息id, name,socketfd, customSocketFd, waitCustomNum
	参数：node:节点指针
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void display_onlineServeNode_basic_information(ONLINESERVENODE *node)
{
    if (node == NULL){
        perr_exit("node is NULL");
    }
    printf("\t\tServe:id %s\tname:%s\t socketfd:%d customSocketFd:%d waitCustomNum:%d", 
	node->id, node->name, node->socketfd, node->waitCustomNum);
}
/*
	功能：打印全部节点信息id, name,socketfd, customSocketFd, waitCustomNume
	参数：head:头节点指针
	返回值：无
	作者：ljj
	时间：2020/8/1
*/
void display_onlineServeNode_all_basic_information(ONLINESERVENODE *head)
{
    if (head == NULL){
        perr_exit("head is NULL");
    }
    ONLINESERVENODE *index = head->next;
	//遍历链表打印id和name
    while (index != NULL){
       display_onlineServeNode_basic_information(index);
       printf("\n");
       index = index->next;
    }
}